package org.infoset.xml.util;

import org.infoset.xml.*;

import java.util.*;

public class XPathUtils {
   
   private XPathUtils() {
   }
   
   /**
    * Returns an xpath to the context node.
    * @param context THe context node to get an xpath for.
    * @param includeBase A true value indicates that the base URI should be used to qualify this node.
    */
   public static String toXPath(Item context,boolean includeBase) {
      if (includeBase) {
         return "document('"+context.getDocument().getBaseURI()+"')"+toXPath(context);
      } else {
         return toXPath(context);
      }
   }
   
   /**
    * Returns an xpath to the context node.
    * @param context The context node to get an xpath for.
    */
   public static String toXPath(Item context) {
      switch (context.getType()) {
         case DocumentItem:
            return "/";            
         case ElementItem: {
            // Count preceding sibilings with same name
            Parent parent = (Parent)context.getOrigin();
            Element element = (Element)context;
            int count = 0;
            for (Child child : parent) {
               if (child!=context) {
                  if (child.getType()==Item.ItemType.ElementItem && ((Element)child).getName().equals(element.getName())) {
                     count++;
                  }
               } else {
                  break;
               }
            }
            count++;
            String qname = element.getNamespaceScope().toQName(element.getName(),true);
            if (qname==null) {
               qname = element.getName().toString();
               //throw new IllegalArgumentException("Element with name "+element.getName()+" is inconsistent with in-scope namespaces; QName cannot be generated.");
            }
            return (parent.getType()==Item.ItemType.DocumentItem? "" : toXPath(parent))+'/'+qname+'['+count+']';
         }
         case AttributeItem: {
            Attribute att = (Attribute)context;
            Element e = (Element)att.getOrigin();
            return toXPath(context.getOrigin())+"/@"+att.getElement().getNamespaceScope().toQName(att.getName(),false);
         }
         case CharactersItem: {
            return toXPath(context.getOrigin())+"/text()";
         }
         case CommentItem: {
            return toXPath(context.getOrigin())+"/comment()";
         }
         case ProcessingInstructionItem: {
            return toXPath(context.getOrigin())+"/processing-instruction()";
         }
      }
      return null;
   }
   
   
}
